//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
// 

#ifndef BITTORRENTFILE_H_
#define BITTORRENTFILE_H_

#include "FilePiece.h"
#include <string>

namespace peermaliziosi {

/**
 * File del torrent.
 * Un torrent puo' contenere piu' di un singolo file. Questi file non vengono considerati
 * singolarmente ma attraverso una loro concatenazione. I pezzi e i blocchi vengono
 * calcolati sulla base di questa concatenazione.
 * Questa classe considera solo la concatenazione di tutti i file.
 */
class BitTorrentFile {
    private:
        /**
         * Contatore di numero di blocchi posseduti
         */
        int countBlocks;
        /**
         * true se il peer ha l'intero file. In questo caso il peer e' un seeder.
         */
        bool have;
        /**
         * Array dei pezzi.
         */
        FilePiece * pieces;
        /**
         * Numero di pezzi
         */
        int numPieces;
        /**
         * Numero di blocchi per pezzo
         */
        int numBlocks;
        /**
         * Usato per il toString()
         */
        std::string strBitfield;

    public:
        // conta il numero di costruttori
        static long countConstructors;
        // conta il numero di distruttori
        static long countDestructors;
        /**
         * Crea un nuovo BitTorrentFile con il numero dato di pezzi
         * @param size numero di pezzi (piece) del file
         */
        BitTorrentFile(int size);
        virtual ~BitTorrentFile();

        // metodi di gestione dei pezzi e dei blocchi
        /**
         * Imposta come posseduto un intero pezzo
         * @param pieceIndex indice del pezzo
         * @return il valore precedente
         */
        bool setPiece(int pieceIndex, bool val);
        /**
         * Imposta come posseduto un singolo blocco
         * @param pieceIndex indice del pezzo
         * @param blockIndex indice del blocco
         * @return il valore precedente
         */
        bool setBlock(int pieceIndex, int blockIndex);
        /**
         * Restituisce true se si possiede un dato blocco
         * @param pieceIndex indice del pezzo
         * @param blockIndex indice del blocco
         * @return vedi descrizione
         */
        bool haveBlock(int pieceIndex, int blockIndex);
        /**
         * Restituisce true se si possiede un intero pezzo
         * @param pieceIndex indice del pezzo
         * @return true se si possiede l'intero pezzo, false altrimenti
         */
        bool havePiece(int pieceIndex);

        /**
         * Restituisce true se si possiede l'intero torrent, false altrimenti
         * @return vedi descrizione
         */
        bool haveTorrent();
        /**
         * Restituisce il numero di pezzi
         * @return vedi descrizione
         */
        int getNumPieces();
        /**
         * Restituisce il numero di blocchi per pezzo
         * @return vedi descrizione
         */
        int getNumBlocksPerPiece();
        /**
         * Restituisce il numero totale di blocchi
         * @return vedi descrizione
         */
        int getTotBlocks();
        /**
         * Controllo sugli indici di pezzo e blocco
         * @param pieceIndex indice del pezzo
         * @param blockIndex indice del blocco
         * @return true se gli indici sono corretti
         */
        bool checkIndex(int pieceIndex, int blockIndex);
        /**
         * Controllo sull'indice di pezzo
         * @param pieceIndex indice del pezzo
         * @return true se l'indice e' corretto
         */
        bool checkIndex(int pieceIndex);
        /**
         * Inizializza i blocchi
         * @param bitfield vettore che verra' inizializzato con il bitfield. La sua dimenenzione
         * deve essere uguale a getNumPieces()
         * @param p probabilita' con coi ogni pezzo viene contrassegnato come posseduto
         * @return il bitfield corrispondente all'inizializzazione
         */
        void initTorrentFile(bool bitfield[], double p);
        /**
         * Stringa corrispondente al bitfield.
         * Formato:
         *  - un punto indica che si e' in possesso di quel blocco
         *  - una croce indica che quel blocco non e' posseduto
         *  - una barra verticale delimita i pezzi
         *
         * es:
         * |.+...|..+++|
         */
        const char* toString();
        /**
         * Restituisce la percentuale di completamento
         */
        float getCompletation();

};

}

#endif /* BITTORRENTFILE_H_ */
